home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / ng_clone.arc / NG_CLONE.PAS < prev    next >
Pascal/Delphi Source File  |  1991-04-28  |  53KB  |  1,385 lines

  1. {$M 4096,0,0}                                    {Reduce stack and heap}
  2. {$R-,I-}                                            {Cut off range and I/O checking} 
  3.  
  4. program ng_clone;                            {After all, that's what it is; Thank you, Mr. Norton, you are among my heroes!} 
  5.  
  6. uses    crt,tesstp5;                        {TESS could probably be the 4.0 version also} 
  7.  
  8. type    gentry=    record                    {General entry type} 
  9.                                 filptr:longint; 
  10.                                 name:string[40]; 
  11.                             end; 
  12.             textel=    record                    {Text-mode screen element} 
  13.                                 cha:byte; 
  14.                                 att:byte; 
  15.                             end; 
  16.             fiftylinebuf=    array[1..50,1..80] of textel;        {Video buffer types} 
  17.             twelwebuf=    array[1..12,1..80] of textel; 
  18.             savedline=    array[1..80] of textel; 
  19.  
  20. var    screen:fiftylinebuf absolute $B800:$0000;                {Text-mode screen, should be B000:0000h on monochrome} 
  21.         csr:word absolute $0040:$0060;                                    {Low-memory cursor info} 
  22.         screenmode:word absolute $0040:$0049;                        {Low-memory screen info} 
  23.         numrows:word absolute $0040:$0084;                            {Low-memory screen info} 
  24.         savedscreen:fiftylinebuf;                                                {Buffer to save current screen on entry} 
  25.         smallscreen:twelwebuf;                                                    {Buffer to hold screen template} 
  26.         menuline:array[0..1] of savedline;                            {Buffer to hold screen template} 
  27.         largescreen:array[0..1] of savedline;                        {Buffer to hold screen template} 
  28.         scrollbuffer:array[0..511] of string[84];                {Buffer to hold guide text entry} 
  29.         infobuffer:array[0..511] of longint;                        {Buffer to hold guide file info} 
  30.         seealso:array[0..19] of gentry;                                    {Buffer to hold guide file info} 
  31.         menu:array[0..2] of string[9]; {Buffer to hold static part of guide menu structure}
  32.         mennu:array[0..3,0..8] of gentry;  {Buffer to hold variable part of guide menu structure}
  33.         backstack:array[0..3] of byte;                                    {TESS background stack} 
  34.         itemlist:array[0..3] of byte;                                        {Menu structure info} 
  35.         menuplaces,menulengths:array[0..6] of byte;            {Stacks for nested menu structures} 
  36.         errorinfo:array[3..6] of string[14];                        {Buffer for error messages} 
  37.         f:file;                                                                                    {The guide file} 
  38.         propath,homedir,streng:string;                                    {String variables, mostly for path and file use} 
  39.         tsrstring:string[8];                                                        {TESS ID string} 
  40.         parent:array[0..3] of longint;                                    {Stack for nested menu structures} 
  41.         poffset:array[0..3] of word;                                        {Stack for nested menu structures} 
  42.         pcurpos:array[0..3] of byte;                                        {Stack for nested menu structures} 
  43.         defptr,stackptr:pointer;                                                {TESS pointers} 
  44.         previous,next:longint;                                                    {Previous and next entry} 
  45.         idnum,i,j,offset,ch,id,bufferlength,savedcsr:word;        {Word variables} 
  46.         erro,wix,wiy,curpos,entrytype,seealsonum,sapos,level,scrtypeflag,startline, 
  47.         txtattri,a1,a2,a3,a4,mlevel,xchoice,ychoice,menux,menuy,menuantal,menunr:byte;        {Byte variables} 
  48.  
  49. procedure hidecrsr; {Make cursor invisible on CGA,EGA or VGA}
  50. begin 
  51.     inline($B4/$01/$B5/$20/$CD/$10); 
  52. end; 
  53.  
  54. function restorecrsr(crsr:word):boolean;                        {Restore saved cursor on CGA,EGA or VGA} 
  55.     inline($B4/$01/$59/$CD/$10); 
  56.  
  57. function key:word;                                                                    {Keyboard interrupt} 
  58.     inline($CD/$16); 
  59.  
  60. procedure keyread(var karakter:word);                                {Readkey replacement} 
  61. var tch:char; 
  62. begin 
  63.     karakter:=key; 
  64.     if (lo(karakter)=0) then {If extended key, add 256 to value of key code}
  65.     begin 
  66.         tch:=char(hi(karakter)); 
  67.         karakter:=ord(tch)+256; 
  68.     end 
  69.     else {Else return key code as is}
  70.     begin 
  71.         tch:=char(lo(karakter)); 
  72.         karakter:=ord(tch); 
  73.     end; 
  74. end; 
  75.  
  76. procedure writestring(cux,cuy,startattr,change,extra:byte;cus:string);        {Direct screen write} 
  77. var jcount,ycount,tmpchr:byte; 
  78.         jch:char; 
  79. begin 
  80.     jcount:=0;ycount:=0;txtattri:=startattr; 
  81.     repeat 
  82.         inc(jcount); 
  83.         jch:=cus[jcount]; 
  84.         if jch<>'^' then                                                    {If not NG control code, write character as is} 
  85.         begin 
  86.             if jch=#255 then                                                {Expand spaces} 
  87.             begin 
  88.                 inc(jcount); 
  89.                 jch:=cus[jcount]; 
  90.                 for ycount:=ycount to ycount+ord(jch) do 
  91.                 begin 
  92.                     screen[cuy,cux+ycount].cha:=32; 
  93.                     screen[cuy,cux+ycount].att:=txtattri; 
  94.                 end; 
  95.             end 
  96.             else 
  97.             begin 
  98.                 screen[cuy,cux+ycount].cha:=ord(jch); 
  99.                 screen[cuy,cux+ycount].att:=txtattri; 
  100.                 inc(ycount); 
  101.             end; 
  102.         end 
  103.         else                                                                            {Control code found!} 
  104.         begin 
  105.             inc(jcount); 
  106.             jch:=cus[jcount]; 
  107.             if ((jch='A') or (jch='a')) then                {Color attribute command} 
  108.             begin 
  109.                 inc(jcount); 
  110.                 jch:=cus[jcount]; 
  111.                 if change=1 then 
  112.                 begin 
  113.                     if ((ord(jch)>47) and (ord(jch)<58)) then txtattri:=ord(jch)-48 else 
  114.                     if ((ord(jch)>64) and (ord(jch)<71)) then txtattri:=ord(jch)-55; 
  115.                     txtattri:=16*txtattri; 
  116.                 end; 
  117.                 inc(jcount); 
  118.                 jch:=cus[jcount]; 
  119.                 if change=1 then 
  120.                 begin 
  121.                     if ((ord(jch)>47) and (ord(jch)<58)) then txtattri:=txtattri+ord(jch)-48 else 
  122.                     if ((ord(jch)>64) and (ord(jch)<71)) then txtattri:=txtattri+ord(jch)-55; 
  123.                 end; 
  124.             end 
  125.             else if ((jch='C') or (jch='c')) then        {Difficult character} 
  126.             begin 
  127.                 inc(jcount); 
  128.                 jch:=cus[jcount]; 
  129.                 if ((ord(jch)>47) and (ord(jch)<58)) then tmpchr:=ord(jch)-48 else 
  130.                 if ((ord(jch)>64) and (ord(jch)<71)) then tmpchr:=ord(jch)-55; 
  131.                 tmpchr:=16*tmpchr; 
  132.                 inc(jcount); 
  133.                 jch:=cus[jcount]; 
  134.                 if ((ord(jch)>47) and (ord(jch)<58)) then tmpchr:=tmpchr+ord(jch)-48 else 
  135.                 if ((ord(jch)>64) and (ord(jch)<71)) then tmpchr:=tmpchr+ord(jch)-55; 
  136.                 screen[cuy,cux+ycount].cha:=tmpchr; 
  137.                 screen[cuy,cux+ycount].att:=txtattri; 
  138.                 inc(ycount); 
  139.             end 
  140.             else if ((jch='b') or (jch='B')) then        {Boldface (?)} 
  141.             begin 
  142.                 if change=1 then 
  143.                 begin 
  144.                     if txtattri=a1 then txtattri:=a3 else txtattri:=a1; 
  145.                 end; 
  146.             end 
  147.             else if ((jch='u') or (jch='U')) then        {Underline (?)} 
  148.             begin 
  149.                 if change=1 then 
  150.                 begin 
  151.                     if txtattri=a1 then txtattri:=a2 else txtattri:=a1; 
  152.                 end; 
  153.             end 
  154.             else if jch='^' then                                        {Write control character itself} 
  155.             begin 
  156.                 screen[cuy,cux+ycount].cha:=ord(jch); 
  157.                 screen[cuy,cux+ycount].att:=txtattri; 
  158.                 inc(ycount); 
  159.             end; 
  160.         end; 
  161.     until jcount>=length(cus); 
  162.     if extra>0 then                                                            {If desired, fill with blanks} 
  163.     begin 
  164.         while ycount<extra do 
  165.         begin 
  166.             screen[cuy,cux+ycount].cha:=32; 
  167.             screen[cuy,cux+ycount].att:=txtattri; 
  168.             inc(ycount); 
  169.         end; 
  170.     end; 
  171. end; 
  172.  
  173. procedure threenitvars;                                                {Initialize variables} 
  174. begin 
  175.     menunr:=0; 
  176.     level:=0; 
  177.     curpos:=0; 
  178.     offset:=0; 
  179.     menux:=3; 
  180.     menuy:=0; 
  181.     mlevel:=0; 
  182.     xchoice:=0; 
  183.     ychoice:=0; 
  184.     sapos:=0; 
  185.     wix:=0;wiy:=0; 
  186.     txtattri:=a1; 
  187. end; 
  188.  
  189. procedure twonitvars;                                                    {Initialize variables} 
  190. begin 
  191.     threenitvars; 
  192.     menuplaces[0]:=5; 
  193.     menuplaces[1]:=15; 
  194.     menuplaces[2]:=28; 
  195.     menuplaces[3]:=39; 
  196.     menuplaces[4]:=0; 
  197.     menuplaces[5]:=0; 
  198.     menuplaces[6]:=0; 
  199.     menulengths[0]:=20; 
  200.     menulengths[1]:=20; 
  201.     menulengths[2]:=20; 
  202.     menulengths[3]:=0; 
  203.     menulengths[4]:=0; 
  204.     menulengths[5]:=0; 
  205.     menulengths[6]:=0; 
  206.     for j:=2 to 79 do smallscreen[1,j].cha:=205; 
  207.     for j:=2 to 79 do smallscreen[2,j].cha:=0; 
  208. end; 
  209.  
  210. procedure initvars;                                                        {Initialize variables} 
  211. var str5:string; 
  212. begin 
  213.     a1:=$70;                                                                            {Color attribute for normal text} 
  214.     a2:=$7E;                                                                            {Color attribute for underline} 
  215.     a3:=$7F;                                                                            {Color attribute for boldface} 
  216.     a4:=$1E;                                                                            {Cursor color attribute} 
  217.     startline:=0; 
  218.     scrtypeflag:=0; 
  219.     twonitvars; 
  220.     errorinfo[3]:='File not found'; 
  221.     errorinfo[4]:='Not an NG file'; 
  222.     errorinfo[5]:='Unexpected EOF'; 
  223.     errorinfo[6]:='Corrupted file'; 
  224.     menu[0]:='Expand'; 
  225.     menu[1]:='Search...'; 
  226.     menu[2]:='Options'; 
  227.     str5:='';propath:=paramstr(0); 
  228.     while (pos('\',propath)>0) do 
  229.     begin 
  230.         str5:=str5+copy(propath,1,pos('\',propath)); 
  231.         propath:=copy(propath,pos('\',propath)+1,length(propath)-(pos('\',propath)+1)); 
  232.     end; 
  233.     propath:=str5; 
  234. end; 
  235.  
  236. procedure initscreen;                                                    {Read screen template from disk} 
  237. var sf:file; 
  238.         numread:word; 
  239. begin 
  240.     assign(sf,propath+'ng_clone.scr'); 
  241.     reset(sf,1); 
  242.     blockread(sf,smallscreen,sizeof(smallscreen),numread); 
  243.     blockread(sf,menuline[1],sizeof(menuline[1]),numread); 
  244.     for i:=1 to 80 do largescreen[0,i]:=smallscreen[5,i]; 
  245.     for i:=1 to 80 do largescreen[1,i]:=smallscreen[11,i]; 
  246.     close(sf); 
  247. end; 
  248.  
  249. procedure removecursor;                                                {Next follows different cursor procedures} 
  250. var sl:byte; 
  251. begin 
  252.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  253.     writestring(2,4+curpos+sl,a1,1,78,scrollbuffer[curpos+offset]); 
  254. end; 
  255.  
  256. procedure insertcursor;                                                {Another cursor procedure} 
  257. var sl:byte; 
  258. begin 
  259.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  260.     writestring(2,4+curpos+sl,a4,0,78,scrollbuffer[curpos+offset]); 
  261. end; 
  262.  
  263. procedure removemenucursor;                                        {Another cursor procedure} 
  264. var sl:byte; 
  265.         cursor:string[78]; 
  266. begin 
  267.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  268.     if menux>2 then cursor:=' '+mennu[menux-3,0].name+' ' else 
  269.     cursor:=' '+menu[menux]+' '; 
  270.     writestring(menuplaces[menux]-1,2+sl,txtattri,0,0,cursor); 
  271. end; 
  272.  
  273. procedure insertmenucursor;                                        {Another cursor procedure} 
  274. begin 
  275.     txtattri:=a4; 
  276.     removemenucursor; 
  277.     txtattri:=a1; 
  278. end; 
  279.  
  280. procedure movemenucursor(direction:byte);            {Another cursor procedure} 
  281. var sl:byte; 
  282. begin 
  283.     if ((entrytype=1) or (level=0)) then 
  284.     begin 
  285.         if scrtypeflag=0 then sl:=startline else sl:=0; 
  286.         txtattri:=a3; 
  287.         removemenucursor; 
  288.         if direction=0 then 
  289.         begin 
  290.             if menux>0 then dec(menux) else menux:=2+menuantal; 
  291.         end 
  292.         else 
  293.         begin 
  294.             if menux<2+menuantal then inc(menux) else menux:=0; 
  295.         end; 
  296.         insertmenucursor; 
  297.         for j:=1 to 80 do menuline[0][j]:=screen[2+sl,j]; 
  298.     end; 
  299. end; 
  300.  
  301. procedure removemlcursor;                                            {Another cursor procedure} 
  302. var    cursor:string[78]; 
  303. begin 
  304.     if ((menux-3=xchoice) and (menuy=ychoice)) then cursor:=#251+' '+mennu[menux-3,menuy+1].name else 
  305.     cursor:='  '+mennu[menux-3,menuy+1].name; 
  306.     while length(cursor)<menulengths[menux]+3 do cursor:=cursor+' '; 
  307.     writestring(2+wix,2+menuy+wiy,txtattri,0,0,cursor); 
  308. end; 
  309.  
  310. procedure insertmlcursor;                                            {Another cursor procedure} 
  311. begin 
  312.     txtattri:=a4; 
  313.     removemlcursor; 
  314.     txtattri:=a1; 
  315. end; 
  316.  
  317. procedure removeseealso;                                            {Another cursor procedure} 
  318. var addo,sl:byte; 
  319.         cursor:string[78]; 
  320. begin 
  321.     addo:=0; 
  322.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  323.     for j:=0 to sapos do 
  324.     begin 
  325.         if j>0 then inc(addo,length(seealso[j-1].name)+2); 
  326.     end; 
  327.     cursor:=' '+seealso[sapos].name+' '; 
  328.     writestring(13+addo,2+sl,txtattri,0,0,cursor); 
  329. end; 
  330.  
  331. procedure insertseealso;                                            {Another cursor procedure} 
  332. begin 
  333.     txtattri:=a4; 
  334.     removeseealso; 
  335.     txtattri:=a1; 
  336. end; 
  337.  
  338. procedure moveseealso(direction:byte);                {You'd never guess: another cursor procedure} 
  339. begin 
  340.     if seealsonum<>255 then 
  341.     begin 
  342.         removeseealso; 
  343.         if direction=0 then 
  344.         begin 
  345.             if sapos>0 then dec(sapos) else sapos:=seealsonum; 
  346.         end 
  347.         else 
  348.         begin 
  349.             if sapos<seealsonum then inc(sapos) else sapos:=0; 
  350.         end; 
  351.         insertseealso; 
  352.     end; 
  353. end; 
  354.  
  355. procedure frame1(w,d:byte);                                        {Frame of line-drawing charcters used for menu} 
  356. begin 
  357.     writestring(wix+1,wiy+1,a1,0,0,' '); 
  358.     for i:=2 to d-1 do 
  359.     begin 
  360.         writestring(1+wix,i+wiy,a1,0,0,' '); 
  361.         writestring(w+wix,i+wiy,a1,0,0,' '); 
  362.     end; 
  363.     writestring(wix+1,wiy+d,a1,0,0,' '); 
  364.     for i:=2 to w-1 do writestring(wix+i,wiy+d,a1,0,0,' '); 
  365.     writestring(wix+i+1,wiy+1,a1,0,0,' '); 
  366.     writestring(wix+i+1,wiy+d,a1,0,0,' '); 
  367. end; 
  368.  
  369. procedure createsmall;                                                {Save current screen and create small screen} 
  370. begin 
  371.     savedscreen:=screen; 
  372.     hidecrsr; 
  373.     for i:=1 to 12 do for j:=1 to 80 do screen[i+startline,j]:=smallscreen[i,j]; 
  374.     writestring(5,2+startline,a3,0,0,menu[0]); 
  375.     writestring(15,2+startline,a3,0,0,menu[1]); 
  376.     writestring(28,2+startline,a3,0,0,menu[2]); 
  377.     writestring(39,2+startline,a3,0,0,mennu[0,0].name); 
  378.     if menuantal>1 then 
  379.     begin 
  380.         i:=length(mennu[0,0].name); 
  381.         menuplaces[4]:=43+i; 
  382.         writestring(43+i,2+startline,a3,0,0,mennu[1,0].name); 
  383.     end; 
  384.     if menuantal>2 then 
  385.     begin 
  386.         inc(i,length(mennu[1,0].name)); 
  387.         menuplaces[5]:=47+i; 
  388.         writestring(47+i,2+startline,a3,0,0,mennu[2,0].name); 
  389.     end; 
  390.     if menuantal>3 then 
  391.     begin 
  392.         inc(i,length(mennu[2,0].name)); 
  393.         menuplaces[6]:=51+i; 
  394.         writestring(51+i,2+startline,a3,0,0,mennu[3,0].name); 
  395.     end; 
  396.     i:=0; 
  397.     while ((i<bufferlength+1) and (i<8)) do 
  398.     begin 
  399.         writestring(2,4+i+startline,a1,1,78,scrollbuffer[i]);inc(i); 
  400.     end; 
  401.     for i:=1 to 12 do for j:=1 to 80 do smallscreen[i,j]:=screen[i+startline,j]; 
  402.     insertmenucursor; 
  403.     screen[5+startline,80].att:=$40; 
  404.     for j:=1 to 80 do menuline[0][j]:=screen[2+startline,j]; 
  405. end; 
  406.  
  407. procedure blank(width,height:byte);                        {Blank part of screen} 
  408. begin 
  409.     for i:=2 to height do for j:=1 to width do 
  410.     begin 
  411.         screen[wiy+i,wix+j].att:=a1; 
  412.         screen[wiy+i,wix+j].cha:=0; 
  413.     end; 
  414. end; 
  415.  
  416. procedure makemenu(num:byte);                                    {Make pull-down menu} 
  417. var windstart,sl:byte; 
  418. begin 
  419.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  420.     if (menulengths[num]+menuplaces[num]+5>79) then windstart:=79-(menulengths[num]+5) else windstart:=menuplaces[num]-2; 
  421.     wix:=windstart-1;wiy:=2+sl; 
  422.     blank(menulengths[num]+4,itemlist[num-3]+1); 
  423.     frame1(menulengths[num]+5,1+itemlist[num-3]); 
  424.     for i:=1 to itemlist[num-3]-1 do 
  425.     begin 
  426.         writestring(4+wix,1+i+wiy,a1,0,0,mennu[num-3,i].name); 
  427.     end; 
  428.     if num-3=xchoice then 
  429.     begin 
  430.         writestring(2+wix,2+ychoice+wiy,a1,0,0,#251); 
  431.     end; 
  432.     insertmlcursor; 
  433.     mlevel:=1; 
  434. end; 
  435.  
  436. procedure writeseealsos(possible_offset:byte);        {Write seealso entries} 
  437. var satmp:word; 
  438. begin 
  439.     if seealsonum<>255 then 
  440.     begin 
  441.         j:=0;satmp:=0; 
  442.         for i:=0 to seealsonum do 
  443.         begin 
  444.             writestring(14+j,2+possible_offset,a1,0,0,seealso[i].name); 
  445.             inc(j,length(seealso[i].name)+2); 
  446.             if i<seealsonum then 
  447.             begin 
  448.                 if (15+j+length(seealso[i+1].name)>79) then 
  449.                 begin 
  450.                     satmp:=i; 
  451.                     i:=seealsonum; 
  452.                 end 
  453.                 else satmp:=0; 
  454.             end; 
  455.         end; 
  456.         if satmp>0 then seealsonum:=satmp; 
  457.         insertseealso; 
  458.     end; 
  459. end; 
  460.  
  461. procedure makesmall(vertical_offset:byte);        {Repaint small screen} 
  462. begin 
  463.     if ((entrytype=1) or (level=0)) then 
  464.     begin 
  465.         for i:=1 to vertical_offset do for j:=1 to 80 do screen[i,j]:=savedscreen[i,j]; 
  466.         for j:=1 to 80 do screen[vertical_offset+1,j]:=smallscreen[1,j]; 
  467.         for j:=1 to 80 do screen[vertical_offset+2,j]:=menuline[0][j]; 
  468.         for i:=3 to 12 do for j:=1 to 80 do screen[i+vertical_offset,j]:=smallscreen[i,j]; 
  469.         for i:=(13+vertical_offset) to lo(numrows)+1 do for j:=1 to 80 do screen[i,j]:=savedscreen[i,j]; 
  470.     end 
  471.     else 
  472.     begin 
  473.         for i:=1 to vertical_offset do for j:=1 to 80 do screen[i,j]:=savedscreen[i,j]; 
  474.         for j:=1 to 80 do screen[vertical_offset+1,j]:=smallscreen[1,j]; 
  475.         for j:=1 to 80 do screen[vertical_offset+2,j]:=menuline[1][j]; 
  476.         for i:=3 to 12 do for j:=1 to 80 do screen[i+vertical_offset,j]:=smallscreen[i,j]; 
  477.         for i:=(13+vertical_offset) to lo(numrows)+1 do for j:=1 to 80 do screen[i,j]:=savedscreen[i,j]; 
  478.         writeseealsos(vertical_offset); 
  479.     end; 
  480.     if entrytype=1 then 
  481.     begin 
  482.         if curpos>7 then 
  483.         begin 
  484.             inc(offset,curpos-7); 
  485.             curpos:=7; 
  486.         end; 
  487.     end; 
  488.     if entrytype=1 then insertcursor; 
  489.     for i:=5 to 10 do screen[i+vertical_offset,80].att:=$07; 
  490.     i:=(((curpos+offset)*6) div (bufferlength+1))+5; 
  491.     if i>10 then i:=10; 
  492.     screen[i+vertical_offset,80].att:=$40; 
  493. end; 
  494.  
  495. procedure makelarge;                                                    {Repaint large screen} 
  496. var    add:byte; 
  497. begin 
  498.     if ((entrytype=1) or (level=0)) then 
  499.     begin 
  500.         for j:=1 to 80 do screen[1,j]:=smallscreen[1,j]; 
  501.         for j:=1 to 80 do screen[2,j]:=menuline[0][j]; 
  502.         for i:=3 to 10 do for j:=1 to 80 do screen[i,j]:=smallscreen[i,j]; 
  503.         for i:=11 to lo(numrows)-1 do for j:=1 to 80 do screen[i,j]:=largescreen[0,j]; 
  504.         for j:=1 to 80 do screen[lo(numrows),j]:=largescreen[1,j]; 
  505.         for j:=1 to 80 do screen[lo(numrows)+1,j]:=smallscreen[12,j]; 
  506.     end 
  507.     else 
  508.     begin 
  509.         for j:=1 to 80 do screen[1,j]:=smallscreen[1,j]; 
  510.         for j:=1 to 80 do screen[2,j]:=menuline[1][j]; 
  511.         for i:=3 to 10 do for j:=1 to 80 do screen[i,j]:=smallscreen[i,j]; 
  512.         for i:=11 to lo(numrows)-1 do for j:=1 to 80 do screen[i,j]:=largescreen[0,j]; 
  513.         for j:=1 to 80 do screen[lo(numrows),j]:=largescreen[1,j]; 
  514.         for j:=1 to 80 do screen[lo(numrows)+1,j]:=smallscreen[12,j]; 
  515.         writeseealsos(0); 
  516.     end; 
  517.     if offset+lo(numrows)-4>bufferlength then 
  518.     begin 
  519.         if bufferlength>offset+lo(numrows)-4 then 
  520.         begin 
  521.             add:=offset-bufferlength+lo(numrows)-4; 
  522.             inc(curpos,add); 
  523.             offset:=bufferlength-lo(numrows)+4; 
  524.         end 
  525.         else 
  526.         begin 
  527.             inc(curpos,offset); 
  528.             offset:=0; 
  529.         end; 
  530.     end; 
  531.     i:=0; 
  532.     while ((i+offset<bufferlength+1) and (i<lo(numrows)-3)) do 
  533.     begin 
  534.         writestring(2,4+i,a1,1,78,scrollbuffer[i+offset]);inc(i); 
  535.     end; 
  536.     if i<lo(numrows)-3 then for i:=i to lo(numrows)-4 do 
  537.     begin 
  538.         writestring(2,4+i,a1,0,78,' '); 
  539.     end; 
  540.     if entrytype=1 then 
  541.     begin 
  542.         if curpos>7 then add:=curpos-7 else add:=0; 
  543.     end 
  544.     else 
  545.     begin 
  546.         add:=0; 
  547.     end; 
  548.     for i:=4 to 11 do for j:=2 to 79 do smallscreen[i,j]:=screen[i+add,j]; 
  549.     if entrytype=1 then insertcursor; 
  550.     for i:=5 to lo(numrows)-1 do screen[i,80].att:=$07; 
  551.     i:=(((curpos+offset)*(lo(numrows)-5)) div (bufferlength+1))+5; 
  552.     if i>lo(numrows)-1 then i:=lo(numrows)-1; 
  553.     screen[i,80].att:=$40; 
  554.     if mlevel=1 then makemenu(menux); 
  555. end; 
  556.  
  557.  
  558. procedure usage;                                                            {Write usage info} 
  559. begin 
  560.     writeln('NG_CLONE USAGE   :'); 
  561.     writeln('------------------'); 
  562.     writeln; 
  563.     writeln('  ng_clone <'+#123+'d:\dir\'+#125+'file'+#123+'.ext'+#125+'> '+#123+ 
  564.     '<d:\ngdir>'+#125+' <+/->  :run NG_CLONE (see below)'); 
  565.     writeln('  ng_clone </u> or </U>                           :remove NG_CLONE if resident'); 
  566.     writeln('  ng_clone </?> or </h> or </H>                   :show this usage information'); 
  567.     writeln; 
  568.     writeln('  The +/- entry is NOT optional, but  used by NG_CLONE to determine whether or'); 
  569.     writeln('  not to install itself as a resident program.'); 
  570. end; 
  571.  
  572. procedure slutlort(b:byte);                                        {Exit on error and display relevant error message} 
  573. begin 
  574.     if b>3 then close(f); 
  575.     if b>2 then 
  576.     begin 
  577.         write('NG_CLONE ERROR #');write(b);writeln(': '+errorinfo[b]+', cannot proceed'); 
  578.     end; 
  579.     if b<3 then usage; 
  580.     halt(0); 
  581. end; 
  582.  
  583. procedure sllut(b:byte); {Error handler without exit, just indicating the error type}
  584. var sl:byte; 
  585. begin 
  586.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  587.     if b>3 then close(f); 
  588.     writestring(4,4+sl,a1,0,74,' '+errorinfo[b]+' - Press any key'); 
  589.     erro:=1; 
  590. end; 
  591.  
  592. function decrypt(b:byte):byte;                                {Decrypt byte from NG format} 
  593. begin 
  594.     if ((b mod 32)>=16) then b:=b-16 else b:=b+16; 
  595.     if ((b mod 16)>=8) then b:=b-8 else b:=b+8; 
  596.     if ((b mod 4)>=2) then b:=b-2 else b:=b+2; 
  597.     decrypt:=b; 
  598. end; 
  599.  
  600. function read_byte:byte;                                            {Read and decrypt byte} 
  601. var tb:byte; 
  602.         numread:word; 
  603. begin 
  604.     blockread(f,tb,1,numread); 
  605.     tb:=decrypt(tb); 
  606.     read_byte:=tb; 
  607. end; 
  608.  
  609. function read_word:word;                                            {Read and decrypt word} 
  610. var tw:word; 
  611.         tb:byte; 
  612. begin 
  613.     tb:=read_byte; 
  614.     tw:=tb; 
  615.     tb:=read_byte; 
  616.     inc(tw,(tb*256)); 
  617.     read_word:=tw; 
  618. end; 
  619.  
  620. function read_long:longint;                                        {Read and decrypt longint} 
  621. var tl:longint; 
  622.         tw:word; 
  623. begin 
  624.     tw:=read_word; 
  625.     tl:=tw; 
  626.     tw:=read_word; 
  627.     inc(tl,(tw*65536)); 
  628.     read_long:=tl; 
  629. end; 
  630.  
  631. procedure read_menu;                                                    {Read a menu structure into the menu buffer} 
  632. var items:word; 
  633. begin 
  634.     mennu[menunr,0].filptr:=filepos(f)-2; 
  635.     seek(f,filepos(f)+2); 
  636.     items:=read_word; 
  637.     itemlist[menunr]:=items; 
  638.     seek(f,filepos(f)+20); 
  639.     for i:=1 to items-1 do 
  640.     begin 
  641.         mennu[menunr,i].filptr:=read_long; 
  642.     end; 
  643.     i:=filepos(f); 
  644.     inc(i,(items*8)); 
  645.     seek(f,i); 
  646.     for i:=0 to items-1 do 
  647.     begin 
  648.         j:=0; 
  649.         repeat 
  650.             mennu[menunr,i].name[j+1]:=chr(read_byte); 
  651.             inc(j); 
  652.         until (mennu[menunr,i].name[j]=#0); 
  653.         mennu[menunr,i].name[0]:=chr(j-1); 
  654.         if j-1>menulengths[menunr+3] then menulengths[menunr+3]:=j-1; 
  655.     end; 
  656.     seek(f,filepos(f)+1); 
  657. end; 
  658.  
  659. procedure skip_short_long;                                        {Skip procedure for the initial menu seek} 
  660. var length:word; 
  661. begin 
  662.     length:=read_word; 
  663.     seek(f,filepos(f)+22+length); 
  664. end; 
  665.  
  666. procedure read_header(modf:byte); {Read NG file header and enter the guide name in the screen template}
  667. var guidenavn:string; 
  668.         buf:array[0..377] of byte; 
  669.         numread:word; 
  670. begin 
  671.     blockread(f,buf,sizeof(buf),numread); 
  672.     if ((buf[0]<>78) or (buf[1]<>71)) then {If the two first characters in the file are not 'NG', the file is no guide}
  673.     begin 
  674.         if modf=0 then slutlort(4) else sllut(4); 
  675.     end; 
  676.     menuantal:=buf[6]; 
  677.     i:=0; 
  678.     repeat 
  679.         guidenavn[i+1]:=chr(buf[i+8]); 
  680.         inc(i); 
  681.     until (buf[i+8]=0); 
  682.     guidenavn[0]:=chr(i); 
  683.     guidenavn:=' The Norton Guide to '+guidenavn+' '; 
  684.     for i:=1 to length(guidenavn) do 
  685.     begin 
  686.         smallscreen[1,39-(length(guidenavn) div 2)+i].cha:=ord(guidenavn[i]); 
  687.     end; 
  688.     seek(f,378); 
  689. end; 
  690.  
  691. procedure read_menus(modf:byte);                            {Initial menu seek, indexing the whole file} 
  692. begin 
  693.     repeat 
  694.         id:=read_word; 
  695.         if id<2 then skip_short_long 
  696.         else 
  697.         if id=2 then 
  698.         begin 
  699.             read_menu; 
  700.             inc(menunr); 
  701.         end 
  702.         else 
  703.         if (id<>5) then 
  704.         begin 
  705.             if (filesize(f)<>filepos(f)) then 
  706.             begin 
  707.                 if modf=0 then slutlort(5) else sllut(5);        {NG file error} 
  708.             end 
  709.             else id:=5; 
  710.         end; 
  711.     until (id=5); 
  712.     if (menunr<>menuantal) then 
  713.     begin 
  714.         if modf=0 then slutlort(6) else sllut(6);                {Incomplete file} 
  715.     end; 
  716. end; 
  717.  
  718. procedure read_strings(totnum:word);                    {Read null-terminated strings into scroll buffer} 
  719. var stringchar:byte; 
  720. begin 
  721.     for i:=1 to totnum do 
  722.     begin 
  723.         j:=0; 
  724.         repeat 
  725.             stringchar:=read_byte; 
  726.             inc(j); 
  727.             scrollbuffer[i-1][j]:=chr(stringchar); 
  728.         until stringchar=0; 
  729.         scrollbuffer[i-1][0]:=chr(j-1); 
  730.     end; 
  731.     bufferlength:=totnum-1; 
  732.     for j:=bufferlength+1 to 511 do scrollbuffer[j]:=''; 
  733. end; 
  734.  
  735. procedure read_short_entry; {Read short entry from file and wring some information out of it}
  736. var items:word; 
  737. begin 
  738.     seek(f,filepos(f)+2); 
  739.     items:=read_word; 
  740.     seek(f,filepos(f)+20); 
  741.     for i:=1 to items do 
  742.     begin 
  743.         seek(f,filepos(f)+2); 
  744.         infobuffer[i-1]:=read_long; 
  745.     end; 
  746.     read_strings(items); 
  747.     entrytype:=1; 
  748. end; 
  749.  
  750. procedure read_long_entry;                                        {Read long entry information} 
  751. var linens,dlength,seealso_num:word; 
  752.         prev,nxt:longint; 
  753.         stringchar:byte; 
  754. begin 
  755.     seek(f,filepos(f)+2); 
  756.     linens:=read_word; 
  757.     dlength:=read_word; 
  758.     seek(f,filepos(f)+10); 
  759.     prev:=read_long; 
  760.     nxt:=read_long; 
  761.     read_strings(linens); 
  762.     if dlength<>0 then                                                        {If there are seealso entries, read them} 
  763.     begin 
  764.         seealso_num:=read_word; 
  765.         for i:=1 to seealso_num do 
  766.         begin 
  767.             if i<21 then seealso[i-1].filptr:=read_long else seek(f,filepos(f)+4); 
  768.         end; 
  769.         for i:=1 to seealso_num do 
  770.         begin 
  771.             if i<21 then 
  772.             begin 
  773.                 j:=0; 
  774.                 repeat 
  775.                     stringchar:=read_byte; 
  776.                     inc(j); 
  777.                     seealso[i-1].name[j]:=chr(stringchar); 
  778.                 until stringchar=0; 
  779.                 seealso[i-1].name[0]:=chr(j-1); 
  780.             end; 
  781.         end; 
  782.         seealsonum:=seealso_num-1; 
  783.         if seealsonum>19 then seealsonum:=19; 
  784.     end 
  785.     else seealsonum:=255; 
  786.     entrytype:=2; 
  787.     previous:=prev; 
  788.     next:=nxt; 
  789. end; 
  790.  
  791. procedure read_entry(fp:longint);                            {Read some kind of file entry} 
  792. begin 
  793.     seek(f,fp); 
  794.     id:=read_word; 
  795.     case id of 
  796.         0:    read_short_entry; 
  797.         1:    read_long_entry; 
  798.     end; 
  799.     if ((id=0) or (level=0)) then parent[level]:=fp; 
  800. end; 
  801.  
  802. procedure scrollinsert(addo_ins,directf:byte);        {Insert for the scroll procedure} 
  803. var sl:byte; 
  804. begin 
  805.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  806.     if directf=0 then dec(offset) else inc(offset); 
  807.     for i:=0 to addo_ins-1 do 
  808.     begin 
  809.         writestring(2,4+i+sl,a1,1,78,scrollbuffer[i+offset]); 
  810.     end; 
  811. end; 
  812.  
  813. procedure scroll(direction:byte);                            {Scroll text screen} 
  814. var addo,sl:byte; 
  815. begin 
  816.     addo:=(scrtypeflag*13)+8; 
  817.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  818.     if scrtypeflag=1 then inc(addo,lo(numrows)-24); 
  819.     if entrytype=1 then 
  820.     begin 
  821.         removecursor; 
  822.         if direction=0 then 
  823.         begin 
  824.             if curpos>0 then 
  825.             begin 
  826.                 dec(curpos); 
  827.             end 
  828.             else 
  829.             begin 
  830.                 if offset>0 then scrollinsert(addo,0); 
  831.             end; 
  832.         end 
  833.         else 
  834.         begin 
  835.             if curpos<addo-1 then 
  836.             begin 
  837.                 if curpos<bufferlength then 
  838.                 begin 
  839.                     inc(curpos); 
  840.                 end; 
  841.             end 
  842.             else 
  843.             begin 
  844.                 if offset+addo<bufferlength+1 then scrollinsert(addo,1); 
  845.             end; 
  846.         end; 
  847.         insertcursor; 
  848.     end 
  849.     else 
  850.     begin 
  851.         if direction=0 then 
  852.         begin 
  853.             if offset>0 then scrollinsert(addo,0); 
  854.         end 
  855.         else 
  856.         begin 
  857.             if offset+addo<bufferlength+1 then scrollinsert(addo,1); 
  858.         end; 
  859.     end; 
  860.     if curpos>7 then addo:=curpos-7 else addo:=0; 
  861.     if scrtypeflag=0 then for i:=4 to 11 do for j:=2 to 79 do smallscreen[i,j]:=screen[i+startline,j] else 
  862.     for i:=4 to 11 do for j:=2 to 79 do smallscreen[i,j]:=screen[i+addo,j]; 
  863.     if scrtypeflag=0 then j:=10 else j:=lo(numrows)-1; 
  864.     for i:=5 to j do screen[i+sl,80].att:=$07; 
  865.     i:=(((curpos+offset)*(j-4)) div (bufferlength+1))+5; 
  866.     if i>j then i:=j; 
  867.     screen[i+sl,80].att:=$40; 
  868. end; 
  869.  
  870. procedure keycommons;                                                    {General screen repaint} 
  871. begin 
  872.     if scrtypeflag=0 then 
  873.     begin 
  874.         makesmall(startline); 
  875.         if entrytype=1 then removecursor; 
  876.         i:=0; 
  877.         while ((i<bufferlength+1) and (i<8)) do 
  878.         begin 
  879.             writestring(2,4+i+startline,a1,1,78,scrollbuffer[i+offset]);inc(i); 
  880.         end; 
  881.         if i<8 then for i:=i to 7 do 
  882.         begin 
  883.             writestring(2,4+i+startline,a1,0,78,' '); 
  884.         end; 
  885.         for i:=4 to 11 do for j:=2 to 79 do smallscreen[i,j]:=screen[i+startline,j]; 
  886.         if entrytype=1 then insertcursor; 
  887.     end 
  888.     else 
  889.     begin 
  890.         makelarge; 
  891.     end; 
  892. end; 
  893.  
  894. procedure pgup;                                                                {Page up procedure for the text screen} 
  895. var addo:byte; 
  896. begin 
  897.     addo:=(scrtypeflag*13)+8; 
  898.     if scrtypeflag=1 then inc(addo,lo(numrows)-24); 
  899.     if entrytype=1 then 
  900.     begin 
  901.         if curpos>0 then 
  902.         begin 
  903.             removecursor; 
  904.             curpos:=1; 
  905.         end 
  906.         else 
  907.         begin 
  908.             dec(offset,addo-2); 
  909.             if ((offset<1) or (offset>10000)) then offset:=1; 
  910.         end; 
  911.     end 
  912.     else 
  913.     begin 
  914.         curpos:=0; 
  915.         dec(offset,addo-2); 
  916.         if ((offset<1) or (offset>10000)) then offset:=1; 
  917.     end; 
  918.     scroll(0); 
  919. end; 
  920.  
  921. procedure pgdn;                                                                {Page down procedure for the text screen} 
  922. var addo:byte; 
  923. begin 
  924.     addo:=(scrtypeflag*13)+8; 
  925.     if scrtypeflag=1 then inc(addo,lo(numrows)-24); 
  926.     if entrytype=1 then 
  927.     begin 
  928.         if curpos<addo-1 then 
  929.         begin 
  930.             removecursor; 
  931.             curpos:=addo-2; 
  932.             if curpos>bufferlength-1 then curpos:=bufferlength-1; 
  933.         end 
  934.         else 
  935.         begin 
  936.             inc(offset,addo-2); 
  937.             if offset+addo>bufferlength then offset:=bufferlength-addo; 
  938.         end; 
  939.     end 
  940.     else 
  941.     begin 
  942.         curpos:=addo-1; 
  943.         inc(offset,addo-2); 
  944.         if offset+addo>bufferlength then offset:=bufferlength-addo; 
  945.         if offset>10000 then offset:=0; 
  946.     end; 
  947.     scroll(1); 
  948. end; 
  949.  
  950. procedure getstreng;                                                    {Read string from keyboard and echo it on screen} 
  951. var chii:word; 
  952.         stl,sl:byte; 
  953.         chin:char; 
  954. begin 
  955.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  956.     streng:='';stl:=0; 
  957.     writestring(15,4+sl,a1+128,0,0,#219); 
  958.     repeat 
  959.         keyread(chii);chin:=chr(lo(chii)); 
  960.         if ((31<chii) and (chii<256) and (length(streng)<62)) then 
  961.         begin 
  962.             writestring(15+stl,4+sl,a1,0,0,upcase(chin)); 
  963.             streng:=streng+upcase(chin); 
  964.             inc(stl); 
  965.             writestring(15+stl,4+sl,a1+128,0,0,#219); 
  966.         end; 
  967.         if ((chii=8) and (length(streng)>0)) then 
  968.         begin 
  969.             writestring(15+stl,4+sl,a1,0,0,#0); 
  970.             streng:=copy(streng,1,length(streng)-1); 
  971.             dec(stl); 
  972.             writestring(15+stl,4+sl,a1+128,0,0,#219); 
  973.         end; 
  974.     until ((chii=13) or (chii=27)); 
  975.     if chii=27 then streng:=''; 
  976. end; 
  977.  
  978. procedure s_o_l_insert;                                                {Insert for the search-or-load procedure} 
  979. var savl:byte; 
  980. begin 
  981.     screen:=savedscreen; 
  982.     if scrtypeflag=1 then 
  983.     begin 
  984.         savl:=startline; 
  985.         startline:=0; 
  986.         createsmall; 
  987.         makelarge; 
  988.         startline:=savl; 
  989.     end 
  990.     else createsmall; 
  991.     insertcursor; 
  992.     makemenu(3); 
  993. end; 
  994.  
  995. procedure exitmenus;                                                    {Remove pull-down menu} 
  996. var add:byte; 
  997. begin 
  998.     mlevel:=0;menuy:=0;wix:=0;wiy:=0; 
  999.     if scrtypeflag=0 then makesmall(startline) else 
  1000.     begin 
  1001.         for j:=1 to 80 do screen[3,j]:=smallscreen[3,j]; 
  1002.         i:=0; 
  1003.         while ((i+offset<bufferlength+1) and (i<9)) do 
  1004.         begin 
  1005.             writestring(2,4+i,a1,1,78,scrollbuffer[i+offset]);inc(i); 
  1006.         end; 
  1007.         if entrytype=1 then insertcursor; 
  1008.         for i:=5 to lo(numrows)-1 do screen[i,80].att:=$07; 
  1009.         i:=(((curpos+offset)*(lo(numrows)-5)) div (bufferlength+1))+5; 
  1010.         if i>lo(numrows)-1 then i:=lo(numrows)-1; 
  1011.         screen[i,80].att:=$40; 
  1012.     end; 
  1013. end; 
  1014.  
  1015. procedure search_or_load(typ:byte;namest:string);        {Search for entry or load new NG file} 
  1016. var sl,savl:byte; 
  1017.         tmpchr:word; 
  1018.         savst:string; 
  1019. begin 
  1020.     if scrtypeflag=0 then sl:=startline else sl:=0; 
  1021.     wix:=2;wiy:=2+sl; 
  1022.     frame1(76,3); 
  1023.     writestring(4,4+sl,a1,0,74,namest); 
  1024.     savst:=streng; 
  1025.     getstreng; 
  1026.     if streng<>'' then 
  1027.     begin 
  1028.         if typ=0 then 
  1029.         begin 
  1030. {SEARCH begins - feel free to add this yourself} 
  1031.             if scrtypeflag=0 then 
  1032.             begin 
  1033.                 makesmall(startline); 
  1034.             end 
  1035.             else 
  1036.             begin 
  1037.                 makelarge; 
  1038.             end; 
  1039.             wix:=0;wiy:=0; 
  1040. {SEARCH ends - feel free to add this yourself} 
  1041.         end 
  1042.         else 
  1043.         begin                                                                                            {Load new guide file} 
  1044.             erro:=0; 
  1045.             if pos('.',streng)=0 then streng:=streng+'.NG'; 
  1046.             if ((pos('\',streng)=0) and (pos(':',streng)=0)) then 
  1047.             writestring(4,4+sl,a1,0,74,' Loading '+homedir+streng+' - please wait') else 
  1048.             writestring(4,4+sl,a1,0,74,' Loading '+streng+' - please wait'); 
  1049.             close(f); 
  1050.             twonitvars; 
  1051.             if ((pos('\',streng)=0) and (pos(':',streng)=0)) then assign(f,homedir+streng) else assign(f,streng); 
  1052.             reset(f,1); 
  1053.             if ioresult<>0 then 
  1054.             begin 
  1055.                 sllut(3); 
  1056.             end; 
  1057.             if erro=0 then 
  1058.             begin 
  1059.                 read_header(1); 
  1060.             end; 
  1061.             if erro=0 then 
  1062.             begin 
  1063.                 read_menus(1); 
  1064.             end; 
  1065.             if erro=0 then 
  1066.             begin 
  1067.                 read_entry(mennu[0,1].filptr); 
  1068.                 s_o_l_insert; 
  1069.             end 
  1070.             else 
  1071.             begin {If there are any errors, we reload the old guide file}
  1072.                 keyread(tmpchr); 
  1073.                 streng:=savst; 
  1074.                 twonitvars; 
  1075.                 if ((pos('\',streng)=0) and (pos(':',streng)=0)) then assign(f,homedir+streng) else assign(f,streng); 
  1076.                 reset(f,1); 
  1077.                 read_header(1); 
  1078.                 read_menus(1); 
  1079.                 read_entry(mennu[0,1].filptr); 
  1080.                 s_o_l_insert; 
  1081.             end; 
  1082.         end; 
  1083.     end 
  1084.     else exitmenus; 
  1085. end; 
  1086.  
  1087. procedure escape_insert;                                            {Insert for the ESC key handler} 
  1088. begin 
  1089.     dec(level); 
  1090.     read_entry(parent[level]); 
  1091.     if ((level>0) or (entrytype=1)) then 
  1092.     begin 
  1093.         curpos:=pcurpos[level];offset:=poffset[level]; 
  1094.     end; 
  1095.     sapos:=0; 
  1096.     keycommons; 
  1097.     ch:=0; 
  1098. end; 
  1099.  
  1100. procedure keyhandler; {Reads key from keyboard and decides which action to take}
  1101. var sl:byte; 
  1102.         tmpchr,tmo,tmc:word; 
  1103. begin 
  1104.     repeat 
  1105.         keyread(ch); 
  1106.         case ch of 
  1107.             43:        begin {'+' key - moves small screen one line down}
  1108.                             if scrtypeflag=0 then 
  1109.                             begin 
  1110.                                 if startline<lo(numrows)-11 then 
  1111.                                 begin 
  1112.                                     inc(startline); 
  1113.                                     for i:=startline+11 downto startline do for j:=1 to 80 do screen[i+1,j]:=screen[i,j]; 
  1114.                                     for j:=1 to 80 do screen[startline,j]:=savedscreen[startline,j]; 
  1115.                                     if mlevel=1 then inc(wiy); 
  1116.                                 end; 
  1117.                             end; 
  1118.                         end; 
  1119.             45:        begin {'-' key - moves small screen one line up}
  1120.                             if scrtypeflag=0 then 
  1121.                             begin 
  1122.                                 if startline>0 then 
  1123.                                 begin 
  1124.                                     dec(startline); 
  1125.                                     for i:=startline to startline+11 do for j:=1 to 80 do screen[i+1,j]:=screen[i+2,j]; 
  1126.                                     for j:=1 to 80 do screen[13+startline,j]:=savedscreen[13+startline,j]; 
  1127.                                     if mlevel=1 then dec(wiy); 
  1128.                                 end; 
  1129.                             end; 
  1130.                         end; 
  1131.             328:    if mlevel=0 then scroll(0) else        {UpArrow key} 
  1132.                         begin 
  1133.                             removemlcursor; 
  1134.                             if menuy>0 then dec(menuy) else menuy:=itemlist[menux-3]-2; 
  1135.                             insertmlcursor; 
  1136.                         end; 
  1137.             336:    if mlevel=0 then scroll(1) else        {DownArrow key} 
  1138.                         begin 
  1139.                             removemlcursor; 
  1140.                             if menuy<itemlist[menux-3]-2 then inc(menuy) else menuy:=0; 
  1141.                             insertmlcursor; 
  1142.                         end; 
  1143.             329:    if mlevel=0 then pgup;                        {PgUp key} 
  1144.             337:    if mlevel=0 then pgdn;                        {PgDn key} 
  1145.             327:    if entrytype=2 then                                {Home key - go to previous entry} 
  1146.                         begin 
  1147.                             if level>0 then 
  1148.                             begin 
  1149.                                 if previous>0 then 
  1150.                                 begin 
  1151.                                     read_entry(previous); 
  1152.                                     curpos:=0;offset:=0;sapos:=0; 
  1153.                                     keycommons; 
  1154.                                 end; 
  1155.                             end; 
  1156.                         end; 
  1157.             335:    if entrytype=2 then                                {End key - go to next entry} 
  1158.                         begin 
  1159.                             if level>0 then 
  1160.                             begin 
  1161.                                 if next>0 then 
  1162.                                 begin 
  1163.                                     read_entry(next); 
  1164.                                     curpos:=0;offset:=0;sapos:=0; 
  1165.                                     keycommons; 
  1166.                                 end; 
  1167.                             end; 
  1168.                         end; 
  1169.             331:    if mlevel=0 then                                    {LeftArrow key} 
  1170.                         begin 
  1171.                             if ((entrytype=1) or (level=0)) then movemenucursor(0) else moveseealso(0); 
  1172.                         end 
  1173.                         else 
  1174.                         begin 
  1175.                             exitmenus; 
  1176.                             movemenucursor(0); 
  1177.                         end; 
  1178.             333:    if mlevel=0 then                                    {RightArrow key} 
  1179.                         begin 
  1180.                             if ((entrytype=1) or (level=0)) then movemenucursor(1) else moveseealso(1); 
  1181.                         end 
  1182.                         else 
  1183.                         begin 
  1184.                             exitmenus; 
  1185.                             movemenucursor(1); 
  1186.                         end; 
  1187.             9    :        begin {Tab key - toggles between small and large screens}
  1188.                             if scrtypeflag=0 then 
  1189.                             begin 
  1190.                                 scrtypeflag:=1; 
  1191.                                 makelarge; 
  1192.                             end 
  1193.                             else 
  1194.                             begin 
  1195.                                 scrtypeflag:=0; 
  1196.                                 makesmall(startline); 
  1197.                                 if mlevel=1 then makemenu(menux); 
  1198.                             end; 
  1199.                         end; 
  1200.             13:        if ((entrytype=1) or (level=0)) then        {ENTER key handler} 
  1201.                         begin 
  1202.                             if menux=0 then 
  1203.                             begin 
  1204.                                 tmc:=curpos;tmo:=offset; 
  1205.                                 pcurpos[level]:=curpos;poffset[level]:=offset; 
  1206.                                 curpos:=0;offset:=0; 
  1207.                                 inc(level); 
  1208.                                 read_entry(infobuffer[tmc+tmo]); 
  1209.                                 keycommons; 
  1210.                             end 
  1211.                             else if menux=1 then 
  1212.                             begin 
  1213.                                 search_or_load(0,' Look for:'); 
  1214.                             end 
  1215.                             else if menux=2 then 
  1216.                             begin 
  1217.                                 search_or_load(1,' New file:'); 
  1218.                             end 
  1219.                             else 
  1220.                             begin 
  1221.                                 if mlevel=0 then makemenu(menux) 
  1222.                                 else 
  1223.                                 begin 
  1224.                                     read_entry(mennu[menux-3,menuy+1].filptr); 
  1225.                                     if entrytype=2 then inc(level); 
  1226.                                     xchoice:=menux-3;ychoice:=menuy; 
  1227.                                     curpos:=0;offset:=0;mlevel:=0;menuy:=0; 
  1228.                                     keycommons; 
  1229.                                 end; 
  1230.                             end; 
  1231.                         end 
  1232.                         else 
  1233.                         begin 
  1234.                             if seealsonum<>255 then 
  1235.                             begin 
  1236.                                 read_entry(seealso[sapos].filptr); 
  1237.                                 curpos:=0;offset:=0;sapos:=0; 
  1238.                                 keycommons; 
  1239.                             end; 
  1240.                         end; 
  1241.             27:        if ((entrytype=2) and (level>0)) then        {ESC key handler} 
  1242.                         begin 
  1243.                             escape_insert; 
  1244.                         end 
  1245.                         else if mlevel=1 then 
  1246.                         begin 
  1247.                             exitmenus; 
  1248.                             ch:=0; 
  1249.                         end 
  1250.                         else 
  1251.                         begin 
  1252.                             if level>0 then 
  1253.                             begin 
  1254.                                 escape_insert; 
  1255.                             end 
  1256.                             else 
  1257.                             begin 
  1258.                                 if scrtypeflag=0 then sl:=startline else sl:=0; 
  1259.                                 wix:=2;wiy:=2+sl; 
  1260.                                 frame1(40,3); 
  1261.                                 writestring(4,4+sl,a3,0,38,' Do you really want to quit (Y/N) ?'); 
  1262.                                 repeat 
  1263.                                     keyread(tmpchr); 
  1264.                                 until ((upcase(chr(lo(tmpchr)))='Y') or (upcase(chr(lo(tmpchr)))='N')); 
  1265.                                 writestring(40,4+sl,a3,0,0,upcase(chr(lo(tmpchr)))); 
  1266.                                 i:=0;while i<65535 do inc(i); 
  1267.                                 if upcase(chr(lo(tmpchr)))='N' then 
  1268.                                 begin 
  1269.                                     if scrtypeflag=0 then makesmall(startline) else makelarge; 
  1270.                                     ch:=0; 
  1271.                                 end; 
  1272.                             end; 
  1273.                         end; 
  1274.         end; 
  1275.     until ch=27; 
  1276. end; 
  1277.  
  1278. function sizeofcode:word;                                            {TESS function to decide size of resident code} 
  1279. var used:word; 
  1280. begin 
  1281.     used:=seg(heapptr^)-prefixseg; 
  1282.     sizeofcode:=used; 
  1283. end; 
  1284.  
  1285. {$F+} procedure tsrmainproc; {$F-}                        {TESS resident procedure entry point} 
  1286. begin 
  1287.   if ((lo(screenmode)<4) or (lo(screenmode)=7)) then 
  1288.   begin 
  1289.     savedcsr:=csr; 
  1290.       threenitvars; 
  1291.       startline:=0; 
  1292.       scrtypeflag:=0; 
  1293.       read_entry(mennu[0,1].filptr); 
  1294.       createsmall; 
  1295.       insertcursor; 
  1296.       makemenu(3); 
  1297.       keyhandler; 
  1298.       screen:=savedscreen; 
  1299.       if restorecrsr(savedcsr) then i:=i; 
  1300.   end 
  1301.   else 
  1302.   begin 
  1303.     tessbeep; 
  1304.   end; 
  1305. end; 
  1306.  
  1307. {$F+} procedure tsrcleanup(removetsr:boolean); {$F-}        {TESS install-or-remove procedure entry point} 
  1308. begin 
  1309.     if (removetsr) then 
  1310.     begin 
  1311.         close(f); 
  1312.         erroraddr:=NIL; 
  1313.     end 
  1314.     else 
  1315.     begin 
  1316.         initscreen; 
  1317.         read_header(0); 
  1318.         read_menus(0); 
  1319.         write('NG_CLONE installed                                            Hotkey: Ctrl-Alt-G'); 
  1320.     end; 
  1321. end; 
  1322.  
  1323. begin                                                                                    {Main loop and command-line parser} 
  1324.     directvideo:=false;                                                    {Force write and writeln through BIOS} 
  1325.     write('Norton Guides Clone V. 1.0                                 (c) 1989 J.P.Pedersen'); 
  1326.     initvars;                                                                        {Initialize global variables} 
  1327.     tsrstring:='NG_CLONE';                                            {TESS ID string - rather original, eh?} 
  1328.   tssetadrtp4(@tsrmainproc,2);                                {Set TESS entry point} 
  1329.   tssetadrtp4(@tsrcleanup,5);                                    {Set TESS entry point} 
  1330.     defptr:=NIL;                                                                {TESS stack pointer #1} 
  1331.     stackptr:=@backstack[(sizeof(backstack)-3)];        {TESS stack pointer #2} 
  1332.     tssetstack(defptr^,stackptr^);                            {Initialize TESS stacks} 
  1333.   if (tscheckresident(tsrstring[1],idnum)=$FFFF) then        {Is NG_CLONE already resident?} 
  1334.     begin 
  1335.         if ((paramstr(1)='/U') or (paramstr(1)='/u')) then            {If uninstall command, then do so} 
  1336.         begin 
  1337.       writeln('NG_CLONE removed from memory'); 
  1338.       i:=tsrelease(idnum); 
  1339.             halt(0); 
  1340.         end 
  1341.         else 
  1342.         begin {Else report presence and exit}
  1343.             write('NG_CLONE already installed                                    Hotkey: Ctrl-Alt-G'); 
  1344.             halt(0); 
  1345.         end; 
  1346.     end 
  1347.   else 
  1348.   begin                                                                                                    {Else} 
  1349.     if ((paramstr(1)='/U') or (paramstr(1)='/u')) then            {If program is not resident, it cannot be removed!} 
  1350.     begin 
  1351.       writeln('NG_CLONE has not been installed!'); 
  1352.       halt(0); 
  1353.     end; 
  1354.   end; 
  1355.     if ((paramstr(1)='/?') or (paramstr(1)='/h') or (paramstr(1)='/H')) then slutlort(0);        {Write usage info and exit} 
  1356.     if paramcount<2 then slutlort(1);                        {Command-line syntax error} 
  1357.     if paramcount>3 then slutlort(2);                        {Command-line syntax error} 
  1358.     streng:=paramstr(1); 
  1359.     if paramcount=3 then homedir:=paramstr(2)+'\' else homedir:='';        {Check for ngdir entry on command-line} 
  1360.     if pos('.',streng)=0 then streng:=streng+'.NG';        {Expand file name} 
  1361.     if ((pos('\',streng)=0) and (pos(':',streng)=0)) then assign(f,homedir+streng) else assign(f,streng); {Expand further}
  1362.     reset(f,1); 
  1363.     if ioresult<>0 then slutlort(3);                        {If file does not exist, terminate and write cause of death} 
  1364.     if (paramstr(paramcount)='+') then                    {Should we go resident?} 
  1365.     begin {OK, we let TESS do the hard work}
  1366.         if (tsdoinit(tsrhot_g,tsrpopalt+tsrpopctrl,tsrusepopup,sizeofcode)<>0) then writeln('Cannot install'); 
  1367.     end 
  1368.     else if (paramstr(paramcount)='-') then                {Non-resident mode wanted} 
  1369.     begin 
  1370.     savedcsr:=csr; 
  1371.         initscreen; 
  1372.         read_header(0); 
  1373.         read_menus(0); 
  1374.         read_entry(mennu[0,1].filptr); 
  1375.         createsmall; 
  1376.         insertcursor; 
  1377.         makemenu(3); 
  1378.         keyhandler; 
  1379.         screen:=savedscreen; 
  1380.         close(f); 
  1381.         if restorecrsr(savedcsr) then i:=i; 
  1382.     end 
  1383.     else slutlort(0); {If there is no (+/-) switch to determine mode , it is an error}
  1384. end. 
  1385.